<?php

namespace App\Http\Controllers\Client\Shop\Explore;

use App\Http\Controllers\ClientController;
use App\Jobs\ExploreRefundJob;
use App\Models\Shop;
use App\Models\Tools\Data;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class ExploreRefundController extends ClientController
{
    private $refund_order = [];

    /**
     * 店主申请退款
     * @return JsonResponse
     */
    public function index()
    {

        $all = $this->all;
        $channel_id = $all['channel_id']; // 等级id
        $refund_number = $all['refund_number']; // 退款数量

        // 检查当前channel_id和we_id是否有正在进行的退款，如果存在，不允许继续退款
        $refunded = DB::table('explore_refund_apply')
            ->where('we_id', '=', $this->we_id)
            ->where('channel_id', '=', $channel_id)
            ->where('finish', '=', 0)
            ->count();
        if ($refunded) {
            return $this->setReturnJson(-1, '您有正在进行的退款，暂时不能申请新的退款');
        }

        // 查询一次，当前订单的价格
        $price = DB::table('explore_channel')
            ->where('channel_id', '=', $channel_id)
            ->sharedLock()
            ->value('price');

        try {
            DB::beginTransaction();

            // 查询探店剩余量
            $remaining = DB::table('explore_remaining')
                ->where('we_id', '=', $this->we_id)
                ->where('channel_id', '=', $channel_id)
                ->lockForUpdate()
                ->first();
            $remaining = json_decode(json_encode($remaining), true);

            if (!$remaining['remaining_times'] || $remaining['remaining_times'] < $refund_number) {
                DB::rollBack();
                return $this->setReturnJson(-1, '您的探店余额次数剩余不足');
            }


            // 查询一年内我的购买订单
            $orders = DB::table('laifei_orders')
                ->where('status', '=', 1) // 已购买成功
                ->where('type', '=', 3) // 探店类型
                ->where('we_id', '=', $this->we_id)
                ->where('outer_id','=',$channel_id)
                ->where('created_at', '>', date("Y-m-d H:i:s", strtotime("-1 year")))
                ->whereRaw('num > refund_num') // 还有余额
                ->lockForUpdate()
                ->orderBy('success_at') // 根据购买成功时间正序排列
                ->get()
                ->toArray();
            $orders = json_decode(json_encode($orders), true);


            // 新增一条退回申请信息
            $apply_id = DB::table('explore_refund_apply')->insertGetId([
                'we_id' => $this->we_id,
                'channel_id' => $channel_id,
                'number' => $refund_number, // 申请退款总数
                'refunded_number' => 0, // 已退款数量
                'refunding_number' => $refund_number, // 正在退款数量
                'return_number' => 0 // 退款失败返回余额数量
            ]);

            // 减去余量表内的订单剩余量
            DB::table('explore_remaining')->where('r_id', '=', $remaining['r_id'])->update([
                'remaining_times' => $remaining['remaining_times'] - $refund_number
            ]);
            // 记录余量变更日志
            DB::table('explore_remaining_log')->insert([
                'r_id' => $remaining['r_id'],
                'action' => Data::DATA_DB_EXPLORE_REMAINING_LOG_TYPE_REFUND,//工单取消退回
                'action_num' => $refund_number,
                'rest_num' => $remaining['remaining_times']- $refund_number,
                'in_use_num' => $remaining['in_use_times'],
            ]);

            // 待计入退款总数数量
            $refund_count = $refund_number;
            // 循环所有订单检查剩余数量,并添加退款单
            foreach ($orders as $order) {
                // 当前订单剩余数量
                $remain_num = $order['num'] - $order['refund_num'];
                // 本次退款数量为待退款数量和当前订单余量的最小值
                $refund_num = min($refund_count, $remain_num);
                // 创建退款单
                $refund_id = DB::table('laifei_refund')->insertGetId([
                    'order_id' => $order['order_id'],
                    'apply_id' => $apply_id,
                    'refund_number' => self::getRefundNumber(),
                    'refund_fee' => $refund_num * $price,
                    'num' => $refund_num,
                ]);
                // 记录到数组，最后统一推送到队列进行退款
                $this->refund_order[] = $refund_id;

                // 如果需要退款的单量小于等于当前剩余数量，那么直接结束
                if ($refund_count <= $remain_num) {
                    $refund_count = 0;
                    break;
                }

                // 减去这次退款的数量
                $refund_count -= $remain_num;
            }

            // 如果还有未退款的，直接计入退款失败的数量内
            if ($refund_count > 0) {
                DB::table('explore_refund_apply')->where('apply_id', '=', $apply_id)->update([
                    'refunding_number' => $refund_number - $refund_count, // 正在退款数量减去剩余数量
                    'return_number' => $refund_count, // 退款失败数量
                ]);
            }

            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            Log::error(ExploreRefundController::class, ['msg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine()]);
            return $this->setReturnJson(-1, '退款失败');
        }
        if(count($this->refund_order)){
            // 根据$this->refund_order退款（队列）
            foreach ($this->refund_order as $refund) {
                ExploreRefundJob::dispatch($refund);
            }
        } else {
            Shop::applyFinish($apply_id);
        }

        return $this->setReturnJson(0, 'success');
    }

    /**
     * 退款单号
     * @return string
     */
    private function getRefundNumber()
    {
        $prefix = env("WECHAT_PAYMENT_PREFIX"); // 订单编号前缀，用于区分测试和生产
        $date = date('Ymd');
        $maxNo = DB::table('laifei_refund')
            ->where('refund_number', 'like', $prefix . $date . '%')
            ->pluck('refund_number')
            ->max();
        $refund_number = $date . '000001';
        if ($maxNo) {
            $no = substr($maxNo, 9);
            $no = (int)$no + 1;
            $no = (string)$no;
            $no = str_pad($no, 6, '0', STR_PAD_LEFT);
            $refund_number = $date . $no;
        }
        return $prefix . $refund_number;

    }

}
